from modStack import Stack
from modCalculatableNumber import CalculatableNumber
from modCalculatablePolynomial import CalculatablePolynomial
from modMonomial import Monomial

'''Writen by Phillip Toussaint
Controls the stack so as to implement the calculator functions'''

class Calc ():

    def __init__(self):

        self.operationStack = Stack();
                
    def add(self):  
        second = self.operationStack.pop()
        if second == None:
            return None
        else:
            first = self.operationStack.pop()
            if first == None:
                self.operationStack.push(second)
                return None
            else:
                result = first+second
                if result == None:
                    result = second + first
                if result == None:
                    self.operationStack.push(first)
                    self.operationStack.push(second)
                else:
                    self.operationStack.push(result)
                return result
    
    def subtract(self):
        second = self.operationStack.pop()
        if second == None:
            return None
        else:
            first = self.operationStack.pop()
            if first == None:
                self.operationStack.push(second)
                return None
            else:
                third = second.__negate__()
                result = first+third
                if result == None:
                    result = third + first
                if result == None:
                    self.operationStack.push(first)
                    self.operationStack.push(second)
                else:
                    self.operationStack.push(result)
                return result
    
    def multiply(self):
        second = self.operationStack.pop()
        if second == None:
            return None
        else:
            first = self.operationStack.pop()
            if first == None:
                self.operationStack.push(second)
                return None
            else:
                result = first*second
                if result == None:
                    result = second * first
                if result == None:
                    self.operationStack.push(first)
                    self.operationStack.push(second)
                else:
                    self.operationStack.push(result)
                return result
       
    def divide(self):
        second = self.operationStack.pop()
        if second == None:
            return None
        else:
            first = self.operationStack.pop()
            if first == None:
                self.operationStack.push(second)
                return None
            else:
                third = second.__invert__()
                if third==None:
                    result = None
                else:
                    result = first*third
                    if result == None:
                        result = third * first
                if result == None:
                    self.operationStack.push(first)
                    self.operationStack.push(second)
                else:
                    self.operationStack.push(result)
                return result

    def createPoly(self):
        second = self.operationStack.pop()
        if second == None:
            return None
        else:
            first = self.operationStack.pop()
            if first == None:
                self.operationStack.push(second)
                return None
            else:
                if isinstance(first, CalculatableNumber) and isinstance(second, CalculatableNumber):
                    if isinstance(second.getVal(), int) or isinstance(second.getVal(), long):
                        result = CalculatablePolynomial( Monomial(int(second.getVal()),float(first.getVal())))
                    else:
                        result = None
                else:
                    result = None
                if result == None:
                    self.operationStack.push(first)
                    self.operationStack.push(second)
                else:
                    self.operationStack.push(result)
                return result        

    def invert(self):  
        first = self.operationStack.pop()
        if first == None:
            return None
        else:
            result = first.__invert__()
            if result == None:
                self.operationStack.push(first)
            else:
                self.operationStack.push(result)
            return result

    def negate(self):  
        first = self.operationStack.pop()
        if first == None:
            return None
        else:
            result = first.__negate__()
            if result == None:
                self.operationStack.push(first)
            else:
                self.operationStack.push(result)
                return result
    
    def square(self):
        first = self.operationStack.pop()
        if first == None:
            return None
        else:
            result = first * first
            if result == None:
                self.operationStack.push(first)
            else:
                self.operationStack.push(result)
                return result
    
    def addItem(self, item):
        self.operationStack.push(item)

    def pop(self):  
        first = self.operationStack.pop()
        if first == None:
            return None
        else:
            return first

    def peek(self, item):
        return self.operationStack.peek(item)
